<template>
  <div class="media-upload">
    <el-row :gutter="20">
      <el-col :span="8">
        <el-card class="course-box" shadow="never">
          <div slot="header" class="card-title">
            <h3>选择合集</h3>
            <span class="card-title-rbtn">
              <el-button type="success" @click="courseDialogShow = true">
                选择合集
              </el-button>

              <el-button
                type="primary"
                v-permission="['course:save']"
                v-if="currentCourse.title"
                @click="$tabs.open({ name: 'CourseDetail', params: { id: currentCourse.id } })"
              >
                编辑合集
              </el-button>
            </span>
          </div>
          <ul>
            <li>选中章节，添加视频，视频将作为该章的正片课</li>
            <li>选中课，添加视频，视频将作为该课的习题课</li>
            <li>习题不可选中</li>
          </ul>

          <el-card shadow="never" v-if="currentCourse.title">
            <div slot="header">
              <!-- <h2 slot="header">{{ currentCourse.title }}</h2> -->
              <el-button icon="el-icon-takeaway-box" @click="clearCurrentCourse">
                清空选择的合集
              </el-button>
              <el-button type="success" icon="el-icon-refresh" @click="refreshCurrentCourse">
                刷新合集信息
              </el-button>
            </div>
            <p v-if="currentCourseTree.length === 0">
              去编辑合集页面增加章节,然后回来刷新吧
            </p>
            <el-tree
              ref="chapterTree"
              :data="currentCourseTree"
              :props="{
                label: 'title',
                children: 'videos',
              }"
              default-expand-all
              :highlight-current="true"
              :expand-on-click-node="false"
              node-key="title"
              @node-click="chapterClick"
            ></el-tree>
          </el-card>
        </el-card>
      </el-col>
      <!-- col -->
      <el-col :span="16">
        <el-card shadow="never" v-if="currentCourseTree.length > 0">
          <div slot="header" class="card-title">
            当前选择节点:
            <h4 class="node-title">{{ currentCourseNode.title }}</h4>
          </div>
          <el-tabs v-model="courseActiveName" v-show="!currentCourseNode.courseId">
            <el-tab-pane label="当前结构下的所有视频" :name="TAB_TYPE_CURRENT">
              <div class="current-video">
                <draggable class="video-list" v-model="currentVideoList" handle=".drag-btn">
                  <video-preview
                    ref="videoPreviewCurrent"
                    v-for="(video, index) in currentVideoList"
                    v-model="currentVideoList[index]"
                    @remove="removeFile(index)"
                    :key="index"
                  ></video-preview>
                </draggable>
                <div
                  class="current-video-btn"
                  sticky-container
                  v-if="courseActiveName === TAB_TYPE_CURRENT"
                >
                  <div v-sticky sticky-offset="{ top: 10 }">
                    <el-button
                      v-permission="['course:list']"
                      @click="videoDialogShow = true"
                      icon="el-icon-plus"
                    >
                      从库中选择
                    </el-button>
                    <el-button
                      type="success"
                      icon="el-icon-check"
                      v-permission="['course:save']"
                      v-show="currentVideoList.length > 0"
                      :loading="saveLoading"
                      @click="saveAllVideoInfo"
                    >
                      保存
                    </el-button>
                    <p class="tips">
                      <span v-show="currentVideoList.length > 0">
                        视频上传成功之后,记得点上边⬆️的"保存信息"按钮!
                      </span>
                    </p>
                  </div>
                </div>
              </div>
            </el-tab-pane>
            <el-tab-pane label="当前等待上传的所有视频" :name="TAB_TYPE_UPLOAD">
              <el-upload
                class="upload-demo"
                ref="mediaUpload"
                drag
                action=""
                :on-change="handleChange"
                :file-list="fileList"
                :show-file-list="false"
                :auto-upload="false"
                accept="video/mp4,video/x-m4v,video/*,.mkv,.rmvb"
                multiple
                v-permission="['course:save']"
              >
                <div>
                  点击上传视频或者将视频文件拖拽到此处
                </div>
              </el-upload>
              <!-- 等待上传的队列 -->
              <div class="current-video">
                <draggable class="video-list" v-model="fileList" handle=".drag-btn">
                  <video-preview
                    ref="videoPreviewWait"
                    v-for="(video, index) in fileList"
                    v-model="fileList[index]"
                    @remove="removeFile(index)"
                    :key="video.uid"
                    :can-drag="uploadedCount == fileList.length"
                  ></video-preview>
                </draggable>
                <div
                  class="current-video-btn"
                  sticky-container
                  v-if="courseActiveName === TAB_TYPE_UPLOAD"
                >
                  <div v-sticky sticky-offset="{ top: 10 }">
                    <el-button
                      type="primary"
                      icon="el-icon-upload"
                      @click="uploadAll"
                      :disabled="!hasWaitUploadImage"
                    >
                      上传视频
                    </el-button>
                    <el-button
                      type="success"
                      :loading="saveLoading"
                      icon="el-icon-check"
                      @click="saveAllVideoInfo"
                    >
                      保存
                    </el-button>
                    <p class="tips">
                      <span v-show="fileList.length > 0">
                        视频上传成功之后,记得点上边⬆️的"保存信息"按钮!
                      </span>
                    </p>
                  </div>
                </div>
              </div>
            </el-tab-pane>
          </el-tabs>
          <div v-show="currentCourseNode.courseId">
            请选择 章 或者 讲 ,进行课程添加
          </div>
        </el-card>
      </el-col>
    </el-row>

    <el-dialog width="80%" :visible.sync="courseDialogShow" append-to-body v-if="courseDialogShow">
      <course-list
        :select-mode="true"
        @single-select="selectCourseHandler"
        @add="closeCourseDialog"
      ></course-list>
    </el-dialog>

    <el-dialog width="80%" :visible.sync="videoDialogShow" append-to-body v-if="videoDialogShow">
      <video-list
        :select-mode="true"
        @check="newVideoCheck"
        :default-search-options="{ single: 1 }"
      ></video-list>
    </el-dialog>
  </div>
</template>

<script>
  import Sticky from 'vue-sticky-directive';
  import VideoPreview from 'comp/VideoPreview';
  import CourseList from 'views/Course/List';
  import VideoList from 'views/Video/List';
  import { cloneDeep } from 'lodash';
  import { ChapterNumber, LessionNumber, PracticeNumber } from 'utils/ChapterNumber';

  export default {
    directives: {
      sticky: Sticky,
    },
    data() {
      return {
        courseActiveName: '',
        courseDialogShow: false,
        currentVideoList: [], //当前章节的已拥有的视频
        currentCourse: {}, // 合集的信息
        currentCourseTree: [], // 合集的章节Tree
        currentCourseNode: {}, // 当前点选的节点

        // Upload Settings
        maxUploadCount: 1000,
        videoDialogShow: false,
        uploadStart: false,
        uploadedCount: 0,
        fileList: [],
        uploaderList: [],
        saveLoading: false,
      };
    },
    const: ['TAB_TYPE_UPLOAD', 'TAB_TYPE_CURRENT'],
    components: {
      VideoPreview,
      CourseList,
      VideoList,
    },
    computed: {
      isUploadPanel() {
        return this.courseActiveName === this.TAB_TYPE_UPLOAD;
      },
      courseId() {
        return this.$route.params.id;
      },
      hasWaitUploadImage() {
        return !!this.fileList.filter((file) => file.status === 'ready');
      },
    },
    watch: {
      $route() {
        if (this.$route.name === 'MediaUpload') {
          this.currentCourse.id = this.$route.params.id || '';
        }
      },
    },
    mounted() {
      this.currentCourse.id = this.$route.params.id || '';
      this.refreshCurrentCourse();
      this.courseActiveName = this.TAB_TYPE_CURRENT;
      this.checkFileList();
    },
    methods: {
      ChapterNumber,
      LessionNumber,
      PracticeNumber,
      AddChapterOrder(list) {
        if (Array.isArray(list)) {
          return list.map((arr, index) => {
            if (arr.chapterId) {
              arr.title = `${this.ChapterNumber(index)} - ${arr.title}`;
            } else if (arr.videoId && arr.kind === 0) {
              arr.title = `${this.LessionNumber(index)} - ${arr.title}`;
            } else if (arr.videoId && arr.kind === 1) {
              arr.title = `${this.PracticeNumber(index)} - ${arr.title}`;
            }
            if (arr.videos) {
              arr.videos = this.AddChapterOrder(arr.videos);
            }
            return arr;
          });
        }
      },
      /**
       * 关闭合集选择弹窗
       */
      closeCourseDialog() {
        this.courseDialogShow = false;
      },
      /**
       * 从库中选择视频
       */
      newVideoCheck(val) {
        this.videoDialogShow = false;
        this.currentVideoList = this.currentVideoList.concat(val);
      },
      /**
       * 清空当前合集
       */
      clearCurrentCourse() {
        this.currentCourse = {};
        this.currentCourseNode = {};
        this.currentCourseTree = [];
        this.currentVideoList = [];
      },
      /**
       * 重新请求当前的合集信息
       */
      refreshCurrentCourse(refreshNode = true) {
        if (!this.currentCourse.id) return;

        this.$service
          .AssetCourseInfo({
            id: this.currentCourse.id,
          })
          .then((res) => {
            // 合集的基本信息
            this.currentCourse = cloneDeep(res);

            if (refreshNode) {
              // 当前节点就是合集
              this.currentCourseNode = cloneDeep(res);
            }
            // 获取合集下的视频
            this.chapterClick(this.currentCourseNode);
            // 获取章节分类
            this.getCateLog();
          });
      },
      /**
       * 获取合集的章节分类
       */
      getCateLog() {
        this.$service
          .AssetCourseCatalog({
            courseId: this.currentCourse.id,
          })
          .then((res) => {
            this.currentCourseTree = this.AddChapterOrder([
              {
                ...this.currentCourse,
                title: this.currentCourse.title,
                videos: res,
              },
            ]);
            // 设置默认选择根节点
            this.$nextTick(() => {
              this.$refs.chapterTree.setCurrentNode(this.currentCourseNode);
            });
          });
      },
      /**
       * 选择了一个合集
       */
      selectCourseHandler(row) {
        if (row.id) {
          this.$tabs.open({ name: 'MediaUpload', params: { id: row.id } });
        }
      },
      /**
       * 节点被点击了
       */
      chapterClick(data, node, self) {
        // 如果是习题就不给点
        if (data.kind === 1) return;
        // 复制被点击的节点
        this.currentCourseNode = cloneDeep(data);
        const { chapterId, videoId } = this.currentCourseNode;
        this.$service
          .AssetCourseVideos({ videoId, chapterId, courseId: this.currentCourse.id })
          .then((res) => {
            this.currentVideoList = res;
          });
      },
      /**
       * 检查是否还有视频没有上传的
       */
      async checkFileList() {
        if (this.fileList.length > 0) {
          return await this.$confirm(
            '当前上传队列中还有未保存的视频信息, 当前操作会导致未保存的数据全部丢失! 是否继续??',
            '提示',
            {
              type: 'error',
            },
          );
        }
        return true;
      },
      /**
       * 检查所有的数据啦
       */
      saveAllVideoInfo() {
        if (this.saveLoading) return;
        this.saveLoading = true;

        const list =
          this.courseActiveName === this.TAB_TYPE_CURRENT
            ? this.$refs.videoPreviewCurrent
            : this.$refs.videoPreviewWait;

        Promise.all(list.map((vpc) => vpc.valid()))
          .then((res) => {
            this.$service
              .AssetVideoSave(
                {
                  // 如果值为null的话, 会被拦截器过滤
                  // 如果是章节下的视频,就用chapterId
                  chapterId: this.currentCourseNode.chapterId,
                  // 如果是讲下面的视频,就用videoId
                  videoId: this.currentCourseNode.videoId,
                  courseId: this.currentCourse.id,
                  videos: this.isUploadPanel ? this.fileList : this.currentVideoList,
                },
                {
                  ...JSON_HEADER,
                },
              )
              .then(() => {
                if (this.isUploadPanel) {
                  this.fileList = [];
                  this.courseActiveName = this.TAB_TYPE_CURRENT;
                }
                this.refreshCurrentCourse(false);
                this.$message.success('保存成功!');
              });
          })
          .catch((err) => {
            console.log(err);
            this.$message.error('有必填项未填写');
          })
          .finally(() => {
            this.saveLoading = false;
          });
      },
      /**
       * 文件列表
       */
      handleChange(file, fileList) {
        this.fileList = [...fileList];
      },
      /**
       * 移除上传队列中的文件
       */
      removeFile(index) {
        if (this.isUploadPanel) {
          this.$confirm(`确认从上传队列中删除 ${this.fileList[index].name} 吗?`).then(() => {
            this.abortUpload(index);
            this.fileList.splice(index, 1);
            this.uploadedCount -= 1;
            if (this.uploaderList[index]) {
              // 删除上传文件
              this.uploaderList[index].deleteFile(0);
              // 清空上传对象
              this.uploaderList[index] = null;
              // 删除上传对象
              this.uploaderList.splice(index, 1);
            }
          });
        } else {
          this.$confirm(`确认从队列中删除 ${this.currentVideoList[index].title} 吗?`).then(() => {
            this.$service
              .AssetCourseRemove({
                courseId: this.currentCourse.di,
                videoId: this.currentVideoList[index].videoId,
              })
              .then((res) => {
                this.chapterClick(this.currentCourseNode);
                this.getCateLog();
                this.$message.success('移除已有的视频成功!');
              });
          });
        }
      },
      /**
       * 取消一个文件上传
       * Doc: https://help.aliyun.com/document_detail/52204.html
       */
      abortUpload(index) {
        const file = this.fileList[index].raw;
        this.$refs.mediaUpload.abort(file);
        // 这里是索引始终都是第0个
        if (this.uploaderList[index]) {
          this.uploaderList[index].cancelFile(0);
          this.$set(this.fileList[index], 'status', 'abort');
        }
      },
      /**
       * 取消一个文件上传
       * Doc: https://help.aliyun.com/document_detail/52204.html
       */
      // resumeUpload(index) {
      //   // 这里是索引始终都是第0个
      //   this.uploaderList[index].resumeFile(0);
      //   this.$set(this.fileList[index], 'status', 'uploading');
      // },
      /**
       * 清空所有上传队列
       */
      clearAll() {
        this.$refs.mediaUpload.clearFiles();
        this.fileList = [];
      },
      /**
       * 上传所有视频
       */
      uploadAll() {
        // if (this.uploadStart) return;
        // this.uploadStart = true;

        this.$notify({
          message: '开始上传啰!~~~~',
          type: 'success',
        });

        this.fileList.forEach(async (file, index) => {
          try {
            if (file.status === 'ready') {
              await this.uploadSingleVideo(index);
            }
          } catch (e) {
            console.log(e);
          }
        });
      },
      /**
       * 上传单个视频
       */
      async uploadSingleVideo(index) {
        const file = this.fileList[index];

        const uploader = new AliyunUpload.Vod({
          userId: process.env.VUE_APP_ALIYUN_ACCOUNT, //阿里账号ID，必须有值
          // partSize: 1048576, //分片大小默认1M，不能小于100K
          // parallel: 5,  //并行上传分片个数，默认5
          // retryCount: 3, //网络原因失败时，重新上传次数，默认为3
          // retryDuration: 2, //网络原因失败时，重新上传间隔时间，默认为2秒
          // enableUploadProgress: true, //是否上报上传日志到点播，默认为true
          // 开始上传
          onUploadstarted: async (uploadInfo) => {
            if (!this.fileList[index]) return;

            this.$set(this.fileList[index], 'status', 'uploading');

            if (uploadInfo.videoId) {
              const { uploadAuth } = await this.$service.AssetUploadRefresh({
                vid: uploadInfo.videoId,
              });
              uploader.resumeUploadWithAuth(uploadAuth);
            } else {
              //从点播服务获取的uploadAuth、uploadAddress和videoId,设置到SDK里
              const { uploadAuth, uploadAddress, videoId } = await this.$service.AssetUploadFetch({
                filename: file.name,
              });
              //获取
              uploader.setUploadAuthAndAddress(uploadInfo, uploadAuth, uploadAddress, videoId);
            }
          },
          // 文件上传成功
          onUploadSucceed: (uploadInfo) => {
            if (!this.fileList[index]) return;

            this.$message.success(`${file.name} 上传成功`);
            this.$set(this.fileList[index], 'status', 'done');
            this.$set(this.fileList[index], 'showVideoId', uploadInfo.videoId);
            this.uploadedCount += 1;
          },
          // 文件上传失败
          onUploadFailed: (uploadInfo, code, message) => {
            this.$message.error(`${file.name}上传失败! Code:${code}, 错误信息:${message}`);
          },
          // 文件上传进度，单位：字节
          onUploadProgress: (uploadInfo, totalSize, loadedPercent) => {
            if (!this.fileList[index]) return;

            const percentage = Math.ceil(loadedPercent * 100);
            this.$set(this.fileList[index], 'percentage', percentage);
          },
          onUploadCanceled() {},
          // 上传凭证超时
          onUploadTokenExpired: async (uploadInfo) => {
            //实现时，根据uploadInfo.videoId调用刷新视频上传凭证接口重新获取UploadAuth
            //https://help.aliyun.com/document_detail/55408.html
            //从点播服务刷新的uploadAuth,设置到SDK里
            const { uploadAuth } = await this.$service.AssetUploadRefresh({
              vid: uploadInfo.videoId,
            });
            uploader.resumeUploadWithAuth(uploadAuth);
          },
        });

        const userData = '{"Vod": {}}';
        uploader.addFile(file.raw, null, null, null, userData);
        uploader.startUpload();
        // uploader和fileList对应起来
        this.uploaderList[index] = uploader;
      },
    },
  };
</script>

<style lang="less" scoped>
  /deep/ .el-tree {
    user-select: none;
  }

  .current-video {
    display: flex;
    .order-container;

    .video-list {
      flex: 1;
    }

    &-btn {
      width: 130px;
      padding: 0 10px;

      /deep/ .el-button {
        margin-bottom: 10px;
        margin-left: 0;
      }
    }
  }

  .node-title {
    padding-left: 10px;
  }

  .upload-demo {
    height: 100px;
    width: 100%;
    margin-bottom: 20px;
  }
</style>

<style lang="less">
  .el-upload {
    display: block;
    height: 100%;
    .el-upload-dragger {
      width: 100%;
      height: 100%;
      display: flex;
      justify-content: center;
      align-items: center;
      color: #aaa;
    }
  }

  .btn-box {
    margin-top: 10px;
  }
</style>
